package syM

import (
	"errors"
	"fmt"
	"db2s/Meta"
	ea "db2s/encryptionAlgorithm"
	"db2s/global"
	"db2s/go-log/log"
	"db2s/parDef"
	"db2s/ref"
	mq "db2s/topic-mq"
	"strings"
	"sync/atomic"
	"time"
)

func errorAction(plan *SchedulePlan2, err any, writeErr string) {
	atomic.SwapInt64(plan.Status.ErrEnd, -1)
	if PlanContext.TaskBarSubsStatusGet(plan.subTaskInfo) != -2 {
		PlanContext.TaskBarSubsStatusSwap(plan.subTaskInfo, "error")
	}
	atomic.SwapInt64(plan.MQ.ErrStatus, -1)
	PlanContext.TaskBarSubsErrorSwap(plan.subTaskInfo, fmt.Sprintf("%v", err))
	PlanContext.TPodTableStatusSwap(plan.TPod.Status, "error")
	log.ErrorLog().Error(writeErr)
}

func metaGlobalInitActive(message mq.Message) (err error) {
	var event = "[metaGlobalInitActive]"
	var plan = message.Properties["plan"].(*SchedulePlan2)
	log.MainLog().Info(fmt.Sprintf("(%v) %v Add migration or verification tasks for Object %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	plan.Status.SubTaskBeginTime = time.Now().UnixNano()
	if GlobalPConfigs.result.Teletypewriter == "bar" {
		PlanContext.TaskBarSubsStatusSwap(plan.subTaskInfo, "running")
		log.MainLog().Info(fmt.Sprintf("(%v) %s Add task Bar Run object %v successfully", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	}
	return
}
func tableJoinMatch(plan *SchedulePlan2) (AlterStatus bool, err error) {
	//判断目标端表是否存在，存在走alter，不存在走create
	var event = "[tableJoinMatch]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start to determine the join method of Table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	if AlterStatus, err = GetTableExist(plan); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The join method for obtaining Table %v failed. error Msg:%v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
	}
	log.MainLog().Info(fmt.Sprintf("(%v) %v The join method in Table %v is %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), func() string {
		if AlterStatus {
			return "join"
		}
		return "left"
	}()))
	return
}
func Comment(plan *SchedulePlan2) (result []any, err error) {
	var comment any
	var event = "[Comment]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the comment information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}})
	if comment, err = c.GetTableCommentMetaST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The comment of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = comment.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The comment of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The comment result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func Character(plan *SchedulePlan2) (result []any, err error) {
	var character any
	var event = "[Character]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the Character information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}})
	if character, err = c.GetTableCharacterMetaST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The Character of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = character.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The Character of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The Character result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func Collation(plan *SchedulePlan2) (result []any, err error) {
	var collation any
	var event = "[Collation]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the Collation information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}})
	if collation, err = c.GetTableCollationMetaST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The Collation of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = collation.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The Collation of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The Collation result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func Constraints(plan *SchedulePlan2) (result []any, err error) {
	var collation any
	var event = "[Collation]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the Collation information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}})
	if collation, err = c.GettableConstraintsST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The Collation of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = collation.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The Collation of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The Collation result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func structBaseQuery(message mq.Message) (err error) {
	var plan = message.Properties["plan"].(*SchedulePlan2)
	var tableMeta = &global.GetTableMeta{}
	var tableMeta1 = &getTableMeta{}
	var event = "[structBaseQuery]"
	defer func() {
		if r := ref.RecoverPanic(event, recover()); err == nil && r != nil {
			err = r
		}
	}()
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start initializing the base information of Table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	if tableMeta1.AlterStatus, err = tableJoinMatch(plan); err != nil {
		return
	}
	if GlobalPConfigs.rules.Struct.Drop && tableMeta1.AlterStatus {
		if _, err = dropObject(plan); err != nil {
			return
		}
		tableMeta1.AlterStatus = false
	}
	if tableMeta1.CommentMe, err = Comment(plan); err != nil {
		return
	}
	if tableMeta1.Constraints, err = Constraints(plan); err != nil {
		return
	}
	if tableMeta1.CharacterMe, err = Character(plan); err != nil {
		return
	}
	if tableMeta1.CollationMe, err = Collation(plan); err != nil {
		return
	}
	log.MainLog().Info(fmt.Sprintf("(%v) %v The base information of Table %v has been initialized successfully", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	if !sendMsg(getCheckMod(), StructIsColumnMeta, getTableName(plan.Object.Schema, plan.Object.Table), getMsgSendData(plan, map[string]any{
		"logSeq": plan.Object.ObjectLogSeq, "tableMeta": tableMeta, "tableMeta1": tableMeta1, "topic": StructIsColumnMeta,
	})) {
		log.ErrorLog().Error(fmt.Sprintf("(%v) %v Table object %v failed to send a message to topic %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), StructIsColumnMeta))
		return errors.New(fmt.Sprintf("send msg fail"))
	}
	plan.MQ.SpeedLimitSwitch = false
	plan.MQ.FirstObjectProductSwap(1)
	plan.MQ.FirstMsgProductAdd()
	plan.MQ.FirstMsgFinishMarkSwap()
	plan.MQ.SecondMsgProductAdd()
	plan.MQ.SecondMsgFinishMarkSwap()
	return
}

func structOptionsCheck(options string) (result bool) {
	for _, v := range GlobalPConfigs.structs.AlterObject {
		if strings.EqualFold(v, options) {
			result = true
			break
		}
	}
	return
}
func structColumnMetaData(message mq.Message) (result []any, err error) {
	var plan = message.Properties["plan"].(*SchedulePlan2)
	var columnMe any
	var event = "[ColumnMeta]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the column metadata information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, plan.SrcParameter, plan.DstParameter)
	if columnMe, err = c.GetColumnMetaST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The column metadata of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = columnMe.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The column metadata of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The column metadata result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func structColumnMetaMapData(message mq.Message, colMeta any) (result []any, err error) {
	var plan = message.Properties["plan"].(*SchedulePlan2)
	var columnMeMap any
	var event = "[ColumnMetaMap]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the column Map metadata information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	srcPar, dstPar := plan.SrcParameter, plan.DstParameter
	switch colMeta.(type) {
	case []any:
		srcPar.Meta = colMeta.([]any)[0]
		dstPar.Meta = colMeta.([]any)[1]
	}
	c.Parameter1 = append(c.Parameter1, srcPar, dstPar)
	if columnMeMap, err = c.GetColMetaMapST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The column Map metadata of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	if columnMeMap != nil {
		for _, v := range columnMeMap.([]any) {
			if v != nil {
				_, _, del := ea.CheckSum().LowerArrCmp(GlobalPConfigs.rules.Struct.AlterSubObject["column"], []string{"name", "type", "null", "default", "comment", "chart", "collate"})
				if v != nil {
					var newO []parDef.ColMetaMapS
					for _, vp := range v.([]parDef.ColMetaMapS) {
						for _, vd := range del {
							switch vd {
							case "chart":
								vp.Charset = ""
							case "collate":
								vp.CollationName = ""
							}
						}
						newO = append(newO, vp)
					}
					result = append(result, newO)
				} else {
					result = append(result, v)
				}
			} else {
				result = append(result, v)
			}
		}
	}
	log.MainLog().Info(fmt.Sprintf("(%v) %v The column Map metadata of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The column Map metadata result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}

func structIndexMetaData(message mq.Message) (result []any, err error) {
	var plan = message.Properties["plan"].(*SchedulePlan2)
	var indexMe any
	var event = "[IndexMeta]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the index metadata information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, plan.SrcParameter, plan.DstParameter)
	if indexMe, err = c.GetNameColumnMetaS(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The column Map metadata of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = indexMe.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The index metadata of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The index metadata result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}

func structPartitionMetaData(message mq.Message) (result []any, err error) {
	var plan = message.Properties["plan"].(*SchedulePlan2)
	var partMe any
	var event = "[PartMeta]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start getting the Part metadata information of table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, plan.SrcParameter, plan.DstParameter)
	if partMe, err = c.GetPartMetaST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The Part metadata of get table %v failed!!! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	result = partMe.([]any)
	log.MainLog().Info(fmt.Sprintf("(%v) %v The Part metadata of get table %v was successful", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	log.MainLog().Debug(fmt.Sprintf("(%v) %v The Part metadata result of table %v is \"%v\" ", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), result))
	return
}
func joinMetaChoose(meta *getTableMeta) (result []any, err error) {
	for i := 0; i < 2; i++ {
		var pp = getTableMeta{
			CommentMe: func() any {
				if meta.CommentMe != nil {
					return meta.CommentMe.([]any)[i]
				}
				return nil
			}(),
			Constraints: func() any {
				if meta.Constraints != nil {
					return meta.Constraints.([]any)[i]
				}
				return nil
			}(),
			CharacterMe: func() any {
				if meta.CharacterMe != nil {
					return meta.CharacterMe.([]any)[i]
				}
				return nil
			}(),
			CollationMe: func() any {
				if meta.CollationMe != nil {
					return meta.CollationMe.([]any)[i]
				}
				return nil
			}(),
			ColumnMe: func() any {
				if meta.ColumnMe != nil {
					return meta.ColumnMe.([]any)[i]
				}
				return nil
			}(),
			ColumnMetaMap: func() any {
				if meta.ColumnMetaMap != nil {
					return meta.ColumnMetaMap.([]any)[i]
				}
				return nil
			}(),
			IndexMe: func() any {
				if meta.IndexMe != nil {
					return meta.IndexMe.([]any)[i]
				}
				return nil
			}(),
			PartMe: func() any {
				if meta.PartMe != nil {
					return meta.PartMe.([]any)[i]
				}
				return nil
			}(),
		}
		pp.ColComparison = meta.ColComparison
		pp.IndexComparison = meta.IndexComparison
		pp.PartComparison = meta.PartComparison
		var p map[string]any
		if p, err = ref.StructToMap(pp); err != nil {
			return
		}
		result = append(result, p)
	}
	return
}
func uniqueValueComparison(src, dst []string) (add, del, eq []string) {
	add, del = ea.CheckSumTypeStruct{}.Arrcmp(src, dst)
	for _, v := range dst {
		var exist bool
	breakLoop:
		for _, d := range del {
			if strings.EqualFold(v, d) {
				exist = true
				break breakLoop
			}
		}
		if !exist {
			eq = append(eq, v)
		}
	}
	return
}
func colTypeComparison(s, d parDef.ColMetaMapS) bool {
	return true
}
func colNullComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{fmt.Sprintf("%v", s.ColNullMap)}, []string{fmt.Sprintf("%v", d.ColNullMap)}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func colCharsetComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{fmt.Sprintf("%v", s.Charset)}, []string{fmt.Sprintf("%v", d.Charset)}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func colCollationComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{fmt.Sprintf("%v", s.CollationName)}, []string{fmt.Sprintf("%v", d.CollationName)}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func colDefaultComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{fmt.Sprintf("%v", s.ColDefaultMap)}, []string{fmt.Sprintf("%v", d.ColDefaultMap)}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func colAutoIncrementComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{fmt.Sprintf("%v", s.ColAutoIncrement)}, []string{fmt.Sprintf("%v", d.ColAutoIncrement)}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func colCommentComparison(s, d parDef.ColMetaMapS) bool {
	var sc, dc = []string{s.ColumnComment}, []string{d.ColumnComment}
	ad, de := ea.CheckSumTypeStruct{}.Arrcmp(sc, dc)
	if len(ad) > 0 || len(de) > 0 {
		return true
	}
	return false
}
func columnEqValueComparison(eq []string, source, target any) (modify []parDef.ColMetaMapS) {
	for _, v := range eq {
		s, _ := source.(map[string]parDef.ColMetaMapS)[v]
		d, _ := target.(map[string]parDef.ColMetaMapS)[v]
		var abnormalType string
		switch {
		case colTypeComparison(s, d):
			abnormalType = "colType"
		case colNullComparison(s, d):
			abnormalType = "colNull"
		case colCharsetComparison(s, d):
			abnormalType = "colCharacter"
		case colCollationComparison(s, d):
			abnormalType = "colCollation"
		case colDefaultComparison(s, d):
			abnormalType = "colDefault"
		case colAutoIncrementComparison(s, d):
			abnormalType = "colAutoIncrement"
		case colCommentComparison(s, d):
			abnormalType = "colComment"
		}
		if len(abnormalType) > 0 {
			//modify = append(modify, v)
		}
	}
	return
}
func colRefMetaMap(colMeta any) (res []parDef.ColMetaMapS, err error) {
	switch colMeta.(type) {
	case map[string]any:
		pp, _ := colMeta.(map[string]any)["columnMetaMap"]
		switch pp.(type) {
		case []parDef.ColMetaMapS:
			res = pp.([]parDef.ColMetaMapS)
		}
	}
	return
}

func columnSubAttributeSet(logo string, src, dst parDef.ColMetaMapS) (ret parDef.ColMetaMapS) {
	var rule string
	var ok bool
	if rule, ok = GlobalPConfigs.rules.Struct.AlterRule["column"][logo]; !ok {
		rule = "src"
	}
	switch rule {
	case "src":
		ret = src
	case "dst":
		ret = dst
	default:
		ret = src
	}
	return
}
func colNameGetMetaMap(name string, colMeta any) (s, t parDef.ColMetaMapS, srcBeforeCol, dstBeforeCol string, err error) {
	var source, target []parDef.ColMetaMapS
	if source, err = colRefMetaMap(colMeta.([]any)[0]); err != nil {
		return
	}
	if target, err = colRefMetaMap(colMeta.([]any)[1]); err != nil {
		return
	}
	for _, src := range source {
		if strings.EqualFold(name, src.ColumnName) {
			s = src
			break
		}
		srcBeforeCol = src.ColumnName
	}
	for _, src := range target {
		if strings.EqualFold(name, src.ColumnName) {
			t = src
			break
		}
		dstBeforeCol = src.ColumnName
	}
	return
}
func colLogoToData(logo string, ret parDef.ColMetaMapS) (res string) {
	switch logo {
	case "null":
		return ret.ColNullMap
	case "chart":
		return ret.Charset
	case "collate":
		return ret.CollationName
	case "default":
		return ret.ColDefaultMap
	case "comment":
		return ret.ColumnComment
	case "seq":
		return ret.ColumnSeq
	}
	return
}
func columnAddDelMeta(add []string, colMeta any) (res []parDef.ColMetaMapS, err error) {
	for _, v := range add {
		var s, t, p parDef.ColMetaMapS
		var srcBef, dstBfe string
		if s, t, srcBef, dstBfe, err = colNameGetMetaMap(v, colMeta); err != nil {
			return nil, err
		}
		p = columnSubAttributeSet("type", s, t)
		p.ColNullMap = colLogoToData("null", columnSubAttributeSet("null", s, t))
		p.Charset = colLogoToData("chart", columnSubAttributeSet("chart", s, t))
		p.CollationName = colLogoToData("collate", columnSubAttributeSet("collate", s, t))
		p.ColDefaultMap = colLogoToData("default", columnSubAttributeSet("default", s, t))
		p.ColumnComment = colLogoToData("comment", columnSubAttributeSet("comment", s, t))
		p.ColumnSeq = colLogoToData("seq", columnSubAttributeSet("seq", s, t))
		p.BeforeColName = func() (rs string) {
			rule, ok := GlobalPConfigs.rules.Struct.AlterRule["column"]["seq"]
			if !ok {
				rule = "src"
			}
			switch rule {
			case "src":
				rs = srcBef
			case "dst":
				rs = dstBfe
			}
			if len(rs) == 0 {
				if p.ColumnSeq == "1" {
					rs = "first"
				} else {
					rs = "end"
				}
			}
			return
		}()
		res = append(res, p)
	}
	return
}
func columnDelMeta(del []string) (res []parDef.ColMetaMapS) {
	for _, v := range del {
		res = append(res, parDef.ColMetaMapS{
			ColumnName: v,
		})
	}
	return
}
func columnComparison(columnMe any, plan *SchedulePlan2) (result colMetaComparison, err error) {
	var res any
	var newAdd, newDel, newModify []parDef.ColMetaMapS
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}, Meta: columnMe.([]any)[0]})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}, Meta: columnMe.([]any)[1]})
	if res, err = c.GetColAttributeMapST(); err != nil {
		return
	}
	source, target := res.([]any)[0], res.([]any)[1]
	var srcUniqueValue, dstUniqueValue []string
	for sk := range source.(map[string]parDef.ColMetaMapS) {
		srcUniqueValue = append(srcUniqueValue, sk)
	}
	for sk := range target.(map[string]parDef.ColMetaMapS) {
		dstUniqueValue = append(dstUniqueValue, sk)
	}
	add, del, eq := uniqueValueComparison(srcUniqueValue, dstUniqueValue)
	if newAdd, err = columnAddDelMeta(add, columnMe); err != nil {
		return
	}
	newDel = columnDelMeta(del)
	newModify = columnEqValueComparison(eq, source, target)
	result.AddColName, result.DelColName, result.ModifyColName = newAdd, newDel, newModify
	return
}
func indexEqValueComparison(eq []string, source, target any) (add, del []string) {
	for _, v := range eq {
		s, _ := source.(map[string][]string)[v]
		d, _ := target.(map[string][]string)[v]
		ad, de := ea.CheckSumTypeStruct{}.Arrcmp(s, d)
		if len(ad) > 0 {
			ad = append(ad, v)
		}
		if len(de) > 0 {
			del = append(del, v)
		}
	}
	return
}
func indexComparison(indexMe any, plan *SchedulePlan2) (result indexMetaComparison, err error) {
	var res any
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}, Meta: indexMe.([]any)[0]})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}, Meta: indexMe.([]any)[1]})
	if res, err = c.GetNameToColumnClipST(); err != nil {
		return
	}
	source, target := res.([]any)[0], res.([]any)[1]
	var srcUniqueValue, dstUniqueValue []string
	for sk := range source.(map[string][]string) {
		srcUniqueValue = append(srcUniqueValue, sk)
	}
	for sk := range target.(map[string][]string) {
		dstUniqueValue = append(dstUniqueValue, sk)
	}
	add, del, eq := uniqueValueComparison(srcUniqueValue, dstUniqueValue)
	newAdd, newDel := indexEqValueComparison(eq, source, target)
	add = append(add, newAdd...)
	del = append(del, newDel...)
	var addInfo, delInfo = make(map[string][]string), make(map[string][]string)
	for _, v := range add {
		switch source.(type) {
		case map[string][]string:
			if pp, ok := source.(map[string][]string)[v]; ok {
				addInfo[v] = pp
			}
		}
	}
	for _, v := range del {
		switch target.(type) {
		case map[string][]string:
			if pp, ok := target.(map[string][]string)[v]; ok {
				delInfo[v] = pp
			}
		}
	}
	result.AddIndexName, result.DelIndexName = addInfo, delInfo
	return
}
func partComparison(indexMe any, plan *SchedulePlan2) (result indexMetaComparison, err error) {
	//var res any
	//c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "join", plan.Object.Role)
	//c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}, Meta: indexMe.([]any)[0]})
	//c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}, Meta: indexMe.([]any)[1]})
	//if res, err = c.GetNameToColumnClipST(); err != nil {
	//	return
	//}
	return
}
func metaComparison(metaData *getTableMeta, plan *SchedulePlan2) (err error) {
	var splitMeta []any
	var event = "[metaComparison]"
	if splitMeta, err = joinMetaChoose(metaData); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The base data cutting of the source table %v failed. error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	if metaData.ColumnMe != nil {
		if metaData.ColComparison, err = columnComparison(splitMeta, plan); err != nil {
			return err
		}
	}
	if metaData.IndexMe != nil {
		if metaData.IndexComparison, err = indexComparison(splitMeta, plan); err != nil {
			return err
		}
	}
	if metaData.PartMe != nil {
		partComparison(metaData.PartMe, plan)
	}
	return
}

func createPrintSql(plan *SchedulePlan2, c *Meta.Meta) (sourcePrintCreate any, err error) {
	var event = "[createPrintSql]"
	c.Join = "left"
	if sourcePrintCreate, err = c.DDLCreateTablePrintST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The print create table sql for generating source table %v failed! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
	}
	return
}
func createGeneralSql(plan *SchedulePlan2, c *Meta.Meta) (triggerGeneralCreate any, err error) {
	c.Join = "right"
	var event = "[createGeneralSql]"
	if triggerGeneralCreate, err = c.DDLCreateTableGeneralST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The exec create table sql for generating Target table %v failed! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
	}
	return
}
func alterGeneralSql(plan *SchedulePlan2, c *Meta.Meta) (triggerGeneralCreate any, err error) {
	c.Join = "right"
	var event = "[alterGeneralSql]"
	if triggerGeneralCreate, err = c.DDLAlterTableGeneralST(); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The exec alter table sql for generating Target table %v failed! error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
	}
	return
}
func alterFixSql(plan *SchedulePlan2, meta *getTableMeta) (result []fixSqlResult, err error) {
	var event = "[alterFixSql]"
	var splitMeta []any
	var sourcePrintCreate, triggerGeneralCreate any
	plan.TPod.Struct.ExecObject = "alter"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start generating the alter statement for Table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	if splitMeta, err = joinMetaChoose(meta); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The base data cutting of the source table %v failed. error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "right", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Meta: splitMeta[0], Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table},
		Options: parDef.Options{
			Scn: GlobalPConfigs.rules.Struct.Scn,
			//StopTime: GlobalPConfigs.rules.Struct.TimeOut,
			AlterDDL: parDef.AlterDDLOptions{
				Rule: GlobalPConfigs.rules.Struct.AlterMethod,
			},
		}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Meta: splitMeta[1], Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable},
		Options: parDef.Options{
			Scn: GlobalPConfigs.rules.Struct.Scn,
			//StopTime: GlobalPConfigs.rules.Struct.TimeOut,
			AlterDDL: parDef.AlterDDLOptions{
				Rule: GlobalPConfigs.rules.Struct.AlterMethod,
			},
		}})
	if triggerGeneralCreate, err = alterGeneralSql(plan, c); err != nil {
		return
	}
	result = append(result, fixSqlResult{
		createSql: triggerGeneralCreate,
		printSql:  sourcePrintCreate,
	})
	log.MainLog().Info(fmt.Sprintf("(%v) %v The alter table statement of Table %v was generated successfully.", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	return
}

// createFixSql 表结构差异修复语句
func createFixSql(plan *SchedulePlan2, meta *getTableMeta) (result []fixSqlResult, err error) {
	var splitMeta []any
	var sourcePrintCreate, triggerGeneralCreate any
	var event = "[createFixSql]"
	log.MainLog().Info(fmt.Sprintf("(%v) %v Start generating the creation statement for Table %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	if splitMeta, err = joinMetaChoose(meta); err != nil {
		errorAction(plan, err, fmt.Sprintf("(%v) %v The base data cutting of the source table %v failed. error Msg: %v", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table), err))
		return
	}
	plan.TPod.Struct.ExecObject = "create"
	c := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName, GlobalPConfigs.dSns.DestDBName}, "left", plan.Object.Role)
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Meta: splitMeta[0], Object: parDef.Object{Schema: plan.Object.Schema, Table: plan.Object.Table}})
	c.Parameter1 = append(c.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Target.GetDB("single"), Meta: splitMeta[0], Object: parDef.Object{Schema: plan.Object.MSchema, Table: plan.Object.MTable}})
	if sourcePrintCreate, err = createPrintSql(plan, c); err != nil {
		return
	}
	if triggerGeneralCreate, err = createGeneralSql(plan, c); err != nil {
		return
	}
	result = append(result, fixSqlResult{
		createSql: triggerGeneralCreate,
		printSql:  sourcePrintCreate,
	})
	log.MainLog().Info(fmt.Sprintf("(%v) %v The create table statement of Table %v was generated successfully.", plan.Object.ObjectLogSeq, event, getTableName(plan.Object.Schema, plan.Object.Table)))
	return
}
